﻿using EasyNet.Componets.Core.Domain;
using EasyNet.Componets.Core.Utils;
using EasyNet.Componets.Data.EntityFramework.Extensions;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EasyNet.Componets.Data.EntityFramework
{
    /// <summary>
    /// EntityFramework 框架实现的 仓储上下文
    /// </summary>
    public class EntityFrameworkRepositoryContext : RepositoryContext, IEntityFrameworkRepositoryContext
    {
        private readonly DbContext _localCtx;

        //上下文级别的事务
        private DbContextTransaction _dbContextTransaction;
        //标识是否开事务
        private bool _isBeginTransaction = false;


        public EntityFrameworkRepositoryContext(DbContext dbContext)
        {
            _localCtx = dbContext;
            _localCtx.Database.Log = LogUtil<EntityFrameworkRepositoryContext>.LogInfo;
        }

        public override void RegisterNew<TAggregateRoot>(TAggregateRoot obj)
        {
            BeginTransation();
            _localCtx.Set<TAggregateRoot>().Add(obj);
            Committed = false;
        }

        public override void RegisterModified<TAggregateRoot>(TAggregateRoot obj)
        {
            BeginTransation();
            //var localObject = _localCtx.Set<TAggregateRoot>().Local.FirstOrDefault(x => x.Id == obj.Id);

            ////若本地跟踪已经存在一个Id相同的聚合根对象，并且跟传入的对象不一致，则Detached掉旧的对象，否则会报错
            ////注意：理论上不应该传入不一致的对象附加，这样子会导致旧对象修改丢失
            ////      新对象只会修改主对象，在附加前修改的导航属性等值不会被跟踪到。
            //if (localObject != null && localObject != obj)
            //{
            //    _localCtx.DetachedEntity(localObject);
            //}

            _localCtx.Entry<TAggregateRoot>(obj).State = EntityState.Modified;

            Committed = false;
        }

        public override void RegisterDeleted<TAggregateRoot>(TAggregateRoot obj)
        {
            BeginTransation();
            _localCtx.Set<TAggregateRoot>().Remove(obj);
            Committed = false;
        }

        public override bool DistributedTransactionSupported
        {
            get { return true; }
        }

        public override void Commit()
        {
            if (!Committed)
            {
                var validationErrors = _localCtx.GetValidationErrors();
                var dbEntityValidationResults = validationErrors as DbEntityValidationResult[] ?? validationErrors.ToArray();
                if (dbEntityValidationResults.Any())
                {
                    throw new DbEntityValidationException("Entity Validation Error", dbEntityValidationResults);
                }

                _localCtx.SaveChanges();
                //提交事务
                CommitTracsation();
                Committed = true;
            }
        }

        public override void Rollback()
        {
            //事务回滚
            _dbContextTransaction.Rollback();
            RejectChanges();
            _isBeginTransaction = false;
        }

        public DbContext Context
        {
            get { return _localCtx; }
        }

        /// <summary>
        /// 回滚缓存模型对象
        /// </summary>
        private void RejectChanges()
        {
            foreach (var entry in _localCtx.ChangeTracker.Entries())
            {
                switch (entry.State)
                {
                    case EntityState.Modified:
                        {
                            entry.CurrentValues.SetValues(entry.OriginalValues);
                            entry.State = EntityState.Unchanged;
                            break;
                        }
                    case EntityState.Deleted:
                        {
                            entry.State = EntityState.Unchanged;
                            break;
                        }
                    case EntityState.Added:
                        {
                            //如果是新增的实体，使其变成游离状态
                            entry.State = EntityState.Detached;
                            break;
                        }
                }
            }
        }

        /// <summary>
        /// 开启事务
        /// </summary>
        private void BeginTransation()
        {
            if (_isBeginTransaction == false)
            {
                _dbContextTransaction = _localCtx.Database.BeginTransaction();
                _isBeginTransaction = true;
            }
        }

        /// <summary>
        /// 提交事务
        /// </summary>
        private void CommitTracsation()
        {
            if (_isBeginTransaction == true && _dbContextTransaction != null)
            {
                _dbContextTransaction.Commit();
                _isBeginTransaction = false;
            }
        }
    }
}
